package com.yourbatis;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MapperFile {

    String regex = "<(\\w+)\\s*\\s*(\\w+\\s*=\\s*\".*?)\"*\\s*>";
    Pattern lineOrStart = Pattern.compile(regex);

    String endRegex = "</(\\w+)>";
    Pattern end = Pattern.compile(endRegex);
    XMLTree root = null;

    String classPath;

    Map<String, XMLTree> sqlNode = new HashMap<>();


    public String getClassPath() {
        if(classPath == null || classPath.isBlank()){
            classPath = root.getAttribute(AttributeType.NAMESPACE);
        }
        return classPath;
    }


    public MapperFile(String path){
        // 解析 xml 文件内容
        try (BufferedReader br = new BufferedReader(new FileReader(path))) {
            String line;
            XMLTree parent = null;
            while ((line = br.readLine()) != null) {
                line = line.trim();

                if (line.startsWith("<!") || line.startsWith("<?") || line.isBlank()) {
                    continue;
                }
                XMLTree current = new XMLTree();
                Matcher matcher = lineOrStart.matcher(line);
                if (matcher.find()) {
                    if (matcher.groupCount() > 0) {
                        current.setParent(parent);
                        // 如果是单行标签
//                        System.err.println(matcher.group());
                        for (int i = 0; i <= matcher.groupCount(); i++) {
                            if(i == 1){
                                current.setTitle(XMLTagType.of(matcher.group(1)));
                            }
                            if(i == 2){
                                // 解析 属性
//                                System.err.println(matcher.group(i));
                                current.setAttributes(parseAttributes(matcher.group(i)));
                            }
                        }
                        if (line.endsWith("/>")) {
//                            parent = current;
                            parent.addChild(current);
                            current.setParent(parent);
                        }else{
                            current.setParent(parent);
                            if(parent != null){
                                parent.addChild(current);
                            }
                            parent = current;
                        }

                        continue;
                    }
                }
                Matcher matcherEnd = end.matcher(line);
                // 处理结束标签
                // 只有单独结束的标签才能包含东西
                if (matcherEnd.find()) {
                    if (matcherEnd.groupCount() > 0) {
                        XMLTagType xmlTagType = XMLTagType.of(matcherEnd.group(1));
                        if(xmlTagType != null && xmlTagType.equals(parent.getTitle())){
                            if(parent != null && parent.getParent() != null){
                                parent = parent.getParent();
                            }
                            continue;
                        }
                        System.err.println("未找到对应的闭合标签");

                    }
                }
                current.getText().append(line);
                current.setParent(parent);
                if(parent != null){
                    parent.addChild(current);
                }
//                parent.getText().append(line);
//                System.err.println(line);
            }
//            System.out.println(parent);
            root = parent;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }



    public Map<AttributeType, String> parseAttributes(String attributes) {
        Map<AttributeType, String> attributesMap = new HashMap<>();
        StringBuilder key = new StringBuilder();
        StringBuilder value = new StringBuilder();
        boolean isKey = true;
        boolean isValue = false;
        boolean start = false;

        for (int i = 0; i < attributes.length(); i++) {
            char c = attributes.charAt(i);
            if(c == '/'){
                continue;
            }
            if (c == '=' && !start) {
                isKey = false;
            } else if (c == '"') {
                if(start){
                    start = false;
                    isValue = false;
                }else{
                    start = true;
                    isValue = true;
                }
//                isValue = !isValue;
            } else if (c == ' ' && !isValue) {
                if (!key.toString().isEmpty()) {

                    attributesMap.put(AttributeType.of(key.toString()), value.toString());
                    key.setLength(0);
                    value.setLength(0);
                    isKey = true;
                    isValue = false;
                }
            } else {
                if (isKey) {
                    key.append(c);
                } else if (isValue) {
                    value.append(c);
                }
            }
        }

        if (!key.toString().isEmpty()) {
            attributesMap.put(AttributeType.of(key.toString()), value.toString());
        }

        return attributesMap;
    }



    public XMLTree getRoot() {
        return root;
    }

    public XMLTree getNode(String nodeName) {
        if(root != null && nodeName.equals(root.getTitle())){
            return root;
        }

        return getNode(nodeName, null, root);
    }

    public XMLTree getNode(String nodeName, String id,  XMLTree xmlTree) {
        if(id == null && nodeName != null){
            if(xmlTree != null && nodeName.equals(xmlTree.getTitle())){
                return xmlTree;
            }
        }
        if(nodeName == null && id != null){
            if(xmlTree != null && id.equals(xmlTree.getAttributes().get(AttributeType.ID))){
                return xmlTree;
            }
        }

        if(xmlTree.getSon() == null){
            return null;
        }
        for (XMLTree son : xmlTree.getSon()) {
            XMLTree node = getNode(nodeName, id, son);
            if(nodeName == null && id != null){
                if(node != null && node.getAttributes().get(AttributeType.ID).equals(id)){
                    return node;
                }
            }
            if(id == null && nodeName != null){
                if(node != null && node.getTitle().equals(nodeName)){
                    return node;
                }
            }

        }
        return null;
    }


    public XMLTree getNodeById(String id) {
        XMLTree xmlTree = sqlNode.get(id);
        if(xmlTree == null){
            xmlTree = getNode(null, id, root);
            sqlNode.put(id, xmlTree);
        }

        return xmlTree;
    }
}
